package com.ndood.code.xml;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.springframework.util.StringUtils;

import com.ndood.code.database.DbUtil;
import com.ndood.code.entity.Column;
import com.ndood.code.entity.Table;
import com.ndood.code.entity.filter.ColumnFilter;
import com.ndood.code.entity.filter.TableFilter;
import com.ndood.code.template.Utils;
import com.ndood.code.util.Unicode;

public class DatabaseXml {

	/**
	 * 写配db.xml置文件
	 * @param tableMap 
	 */
	public static void writeDatabaseXml(DbUtil util, Map<String, String> propertyMap, String outPath, Map<String, TableFilter> tableMap)
			throws ClassNotFoundException, SQLException {
		Document doc = DocumentHelper.createDocument();//
		doc.setXMLEncoding("utf-8");

		// Step1: 生成父xml标签
		Element root = doc.addElement("db");
		root.addAttribute("name", util.getDbName());//
		root.addAttribute("driverName", util.getDriverName());//
		root.addAttribute("userName", util.getUserName());//
		root.addAttribute("passWord", util.getPassWord());//
		root.addAttribute("url", util.getUrl());//

		// Step2: 生成全局db数据
		for (String key : propertyMap.keySet()) {
			Element element = root.addElement("property");
			element.addAttribute("name", key);
			element.setText(propertyMap.get(key));
		}

		// Step3: 生成每个表格的数据
		List<Table> tableList = util.getDbInfo();
		for (Table table : tableList) {
			
			// 过滤掉不需要生成的数据表
			if(tableMap.get(table.getName())==null) {
				continue;
			}
			TableFilter tableFilter = tableMap.get(table.getName());
			
			int keycount = 0;// 主键数量
			for (Column column : table.getColumns()) {
				if (column.getColumnKey().equals("PRI")) {
					keycount++;
				}
			}
			
			if (keycount == 1) {// 只生成带一个主键的数据表
				
				Element tableElement = root.addElement("table");//
				tableElement.addAttribute("name", table.getName());// 表名称
				tableElement.addAttribute("name2", Utils.getTableName2(table.getName())); // 处理后的表名称（去掉前缀）
				tableElement.addAttribute("comment", Unicode.toUnicodeString(table.getComment()));
				tableElement.addAttribute("key", table.getKey());
				
				// 为表添加附加属性
				String subpackage = tableFilter.getSubpackage();
				tableElement.addAttribute("subpackage", tableFilter.getSubpackage());
				tableElement.addAttribute("subpackagePath", Utils.getSubpackagePath(subpackage));
				tableElement.addAttribute("subpackageDot", Utils.getSubpackageDot(subpackage));
				tableElement.addAttribute("subpackageHump", Utils.getSubpackageHump(subpackage));
				tableElement.addAttribute("prefixSubpackage", Utils.getPrefixSubpackage(subpackage));
				tableElement.addAttribute("prefixSubpackagePath", Utils.getPrefixSubpackagePath(subpackage));
				tableElement.addAttribute("prefixSubpackageDot", Utils.getPrefixSubpackageDot(subpackage));
				tableElement.addAttribute("prefixSubpackageHump", Utils.getPrefixSubpackageHump(subpackage));
				tableElement.addAttribute("title", tableFilter.getTitle());

				for (Column column : table.getColumns()) {
					
					Element columnElement = tableElement.addElement("column");
					columnElement.addAttribute("name", column.getColumnName());// 字段名称
					columnElement.addAttribute("name2", Utils.getColumnName2(column.getColumnName()));// 处理后的列名称
					columnElement.addAttribute("type", column.getColumnType());// 类型
					columnElement.addAttribute("dbtype", column.getColumnDbType());
					columnElement.addAttribute("comment", Unicode.toUnicodeString(column.getColumnComment()));
					columnElement.addAttribute("key", column.getColumnKey()); // 主键
					columnElement.addAttribute("decimal_digits", String.valueOf(column.getDecimal_digits())); // 精度
					columnElement.addAttribute("colums_size", String.valueOf(column.getColums_size())); // 位数
					
					// 为列添加附加属性
					ColumnFilter columnFilter = null;
					for (String colName : tableFilter.getColumnsMap().keySet()) {
						if(column.getColumnName().equals(colName)) {
							columnFilter = tableFilter.getColumnsMap().get(colName);
							break;
						}
					}
					if(columnFilter!=null) {
						columnElement.addAttribute("componentType",columnFilter.getComponentType());
						columnElement.addAttribute("search", columnFilter.getSearch());
						columnElement.addAttribute("hideColumn", columnFilter.getHideColumn());
					}else {
						columnFilter = new ColumnFilter();
						columnElement.addAttribute("componentType",columnFilter.getComponentType());
						columnElement.addAttribute("search", columnFilter.getSearch());
						columnElement.addAttribute("hideColumn", columnFilter.getHideColumn());
					}
					
				}
			}

		}
		writeXml(outPath, doc);
	}

	/**
	 * 返回表名称
	 */
	@SuppressWarnings("unchecked")
	public static List<Table> readDatabaseXml(String xmlPath) {
		List<Table> list = new ArrayList<Table>();
		try {
			SAXReader reader = new SAXReader();

			File file = new File(xmlPath + "\\db.xml");
			Document doc = reader.read(file);

			Element dbe = doc.getRootElement();
			List<Element> elist = dbe.elements();
			for (Element e : elist) {
				if (e.getName().equals("table")) {

					Table table = new Table();
					table.setName(e.attributeValue("name"));
					table.setName2(e.attributeValue("name2"));
					table.setComment(Unicode.decodeUnicode(e.attributeValue("comment")));
					table.setKey(e.attributeValue("key"));
					
					table.setSubpackage(e.attributeValue("subpackage"));
					table.setSubpackagePath(e.attributeValue("subpackagePath"));
					table.setSubpackageDot(e.attributeValue("subpackageDot"));
					table.setSubpackageHump(e.attributeValue("subpackageHump"));
					
					table.setPrefixSubpackage(e.attributeValue("prefixSubpackage"));
					table.setPrefixSubpackagePath(e.attributeValue("prefixSubpackagePath"));
					table.setPrefixSubpackageDot(e.attributeValue("prefixSubpackageDot"));
					table.setPrefixSubpackageHump(e.attributeValue("prefixSubpackageHump"));
					
					// 添加导航标题
					String title = e.attributeValue("title");
					if(!StringUtils.isEmpty(title)) {
						String[] arr = title.split(",");
						for (String routeTitle : arr) {
							table.getTitles().add(routeTitle);
						}
					}
					
					List<Column> columns = new ArrayList<Column>();
					List<Element> elist2 = e.elements(); // 字段列表

					for (Element e2 : elist2) {
						Column column = new Column();
						column.setColumnName(e2.attributeValue("name"));
						column.setColumnName2(e2.attributeValue("name2"));
						column.setColumnType(e2.attributeValue("type"));
						column.setColumnDbType(e2.attributeValue("dbtype"));
						column.setColumnComment(Unicode.decodeUnicode(e2.attributeValue("comment")));
						column.setColumnKey(e2.attributeValue("key"));
						column.setComponentType(e2.attributeValue("componentType"));
						column.setHideColumn("true".equals(e2.attributeValue("hideColumn")));
						column.setSearch("true".equals(e2.attributeValue("search")));
						columns.add(column);
					}
					table.setColumns(columns);
					list.add(table);
				}

			}

		} catch (DocumentException e) {
			e.printStackTrace();
		}

		return list;
	}

	/**
	 * 读取数据库全局属性
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, String> readProperty(String xmlPath) {
		Map<String, String> map = new HashMap<String, String>();
		try {
			SAXReader reader = new SAXReader();
			File file = new File(xmlPath + "\\db.xml");
			Document doc = reader.read(file);

			Element dbe = doc.getRootElement();
			List<Element> elist = dbe.elements();
			for (Element e : elist) {
				if (e.getName().equals("property")) {
					map.put(e.attributeValue("name"), e.getText());
				}
			}
		} catch (DocumentException e) {
			e.printStackTrace();
		}

		return map;
	}

	/**
	 * 写出到xml
	 */
	private static void writeXml(String outPath, Document doc) {
		try {
			String xmlFileName = "db.xml";
			OutputFormat format = OutputFormat.createPrettyPrint();
			format.setEncoding("UTF-8");

			XMLWriter writer = null;

			File file = new File(outPath + "/" + xmlFileName);

			if (!file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
			}
			writer = new XMLWriter(new FileWriter(file), format);
			writer.write(doc);
			writer.close();

		} catch (IOException e) {

		}
	}

}
